"""
内联回调函数

问题：
    当你编写使用回调函数的代码的时候，担心很多小函数的扩张可能会弄乱程序控制流。
    你希望找到某个方法来让代码看上去更像是一个普通的执行序列。
解决方案：
    通过使用生成器和协程可以使得回调函数内联在某个函数中。
"""

from queue import Queue
from functools import wraps


def apply_async(func, args, *, callback):
    result = func(*args)

    callback(result)


class Async:
    def __init__(self, func, args):
        self.func = func
        self.args = args


def inline_async(func):
    @wraps(func)
    def wrapper(*args):
        f = func(*args)
        result_queue = Queue()
        result_queue.put(None)
        while True:
            result = result_queue.get()
            try:
                a = f.send(result)
                apply_async(a.func, a.args, callback=result_queue.put)
            except StopIteration:
                break

    return wrapper


def add(x, y):
    return x + y


@inline_async
def use_add():
    r = yield Async(add, (2, 3))
    print(r)
    for i in range(3):
        r = yield Async(add, (i, i))
        print(r)
    # 输出结果：
    """
    5
    0
    2
    4
    """


if __name__ == '__main__':
    use_add()
